import * as THREE from "three";
import * as geolib from "geolib";
import jsonData from '../json/building.json';

interface BuildingOption {
    customCoords?: {
        lngLatsToCoords: (coords: number[][][]) => number[][][];
    };
}

// 中心点经纬度（根据实际场景调整）
const center = [121.058685, 37.658918] as [number, number];
// 坐标缩放因子（控制建筑在3D场景中的大小）
const COORD_SCALE = 100;

export default function useBuilding(opt?: BuildingOption) {
    const group = new THREE.Group();
    // const buildingJsonData = geojson2gcj02(jsonData)
    const buildingJsonData = jsonData
    buildingJsonData.features.forEach((elem: any) => {
        const building = new THREE.Object3D();
        let info = elem.properties;
        let coordinates = elem.geometry.coordinates;
        // coordinates 这里是三维数组[[[[x,y],[x,y]]]], 如果是二维数组记得去除遍历
        // coordinates.forEach(multiPolygon => { }
        if (opt && opt.customCoords) {
            coordinates = coordinates.map((item: any) => {
                return opt.customCoords?.lngLatsToCoords(item)
            });
        }
        const { geometry } = getBuilding(coordinates, info, info.height * 0.01);
        const material = new THREE.MeshStandardMaterial({
            // metalness: 1,
            // roughness: 1,
            color: 0x3C6999,
            // transparent: true,
            // opacity: 1
        });
        const texLoader = new THREE.TextureLoader()
        const texture = texLoader.load('./source/textures/waternormals.jpg');
        // texture.encoding = THREE.sRGBEncoding
        const material1 = new THREE.MeshLambertMaterial({
            color: 0x3C6999, //设置材质颜色
            transparent: false, //开启透明
            opacity: 0.95, //设置透明度
            // wireframe: true,
            map: texture,
        });

        const mesh = new THREE.Mesh(geometry, [
            material,
            material1
        ]);
        building.scale.set(1, 1, 1);
        building.add(mesh)
        // building.add(hepler);
        group.add(building);
    });

    // group.rotation.z = Math.PI;
    // group.position.set(0, 0, 0);
    return {
        building: group
    }
}

/** 生成建筑形状 */
function genShape(points: number[][]): THREE.Shape {
    const shape = new THREE.Shape();
    if (points.length < 3) {
        throw new Error("建筑轮廓点数量不足（至少需要3个点）");
    }

    points.forEach((point, i) => {
        // 将经纬度转换为3D场景坐标（关键修复）
        const [x, y] = GPSRelativePosition([point[0]!, point[1]!]);
        if (i === 0) {
            shape.moveTo(x, y);
        } else {
            shape.lineTo(x, y);
        }
    });
    return shape;
}

function genHelper(geometry: THREE.ExtrudeGeometry) {
    if (!geometry.boundingBox) {
        geometry.computeBoundingBox();
    }
    let box3 = geometry.boundingBox;
    if(box3) {
        if (!isFinite(box3.max.x!)) {
            return false;
        }
        let helper = new THREE.Box3Helper(box3, 0xffff00);
        helper.updateMatrixWorld();
        return helper;
    }
    return null;
}

function getBuilding(data = [], info: any, height = 1) {
    let shape: any;
    let holes: any[] = [];
    for (let i = 0; i < data.length; i++) {
        const el: any = data[i];
        if (i == 0) {
            shape = genShape(el)
        } else {
            holes.push(genShape(el))
        }
    }
    for (let i = 0; i < holes.length; i++) {
        shape.holes.push(holes[i]);
    }
    const geometry = new THREE.ExtrudeGeometry(shape, {
        curveSegments: 1,
        depth: height * 1,
        bevelEnabled: false
    });
    // 重新计算当前几何体对象的立方体界限
    // geometry.computeBoundingBox()
    // geometry.computeBoundingSphere()

    let hepler = genHelper(geometry);
    if (hepler) {
        hepler.name = info['id'] || 'building';
        // hepler.info = info;
    }
    return {
        geometry,
        hepler
    }
}

/** 经纬度转3D场景坐标（关键修复） */
function GPSRelativePosition(objPosi: [number, number]): [number, number] {
    const [lng, lat] = objPosi;
    const [centerLng, centerLat] = center;

    // 计算两点距离（米）和方位角（度）
    const distance = geolib.getDistance(
        { latitude: lat, longitude: lng },
        { latitude: centerLat, longitude: centerLng }
    );
    const bearing = geolib.getRhumbLineBearing(
        { latitude: lat, longitude: lng },
        { latitude: centerLat, longitude: centerLng }
    );

    // 角度转弧度（修复：使用180而非100）
    const radians = bearing * Math.PI / 180;

    // 计算相对坐标（x: 东西方向，y: 南北方向）
    const x = distance * Math.cos(radians);
    const y = distance * Math.sin(radians);

    // 缩放并调整方向（确保在场景中可见）
    return [-x / COORD_SCALE, y / COORD_SCALE];
}